﻿using System.Collections.Concurrent;
using System.ComponentModel;
using BP.Plugin.Monitor.Application.Common.Interfaces;
using BP.Plugin.Monitor.Application.Features.OnlineUsers.Commands.BatchDelete;
using BP.Plugin.Monitor.Application.Features.OnlineUsers.DTOs;
using BP.Plugin.Monitor.Application.Features.OnlineUsers.Queries.PaginationQuery;
using BP.Plugin.Monitor.Application.Features.SystemLogs.Commands.BatchDelete;
using BP.Plugin.Monitor.Application.Features.SystemLogs.Commands.SyncLog;
using BP.Plugin.Monitor.Application.Features.SystemLogs.DTOs;
using BP.Plugin.Monitor.Application.Features.SystemLogs.Queries.PaginationQuery;
using BP.Plugin.Monitor.Domain.Entities;
using Core.Attributes;
using Core.Authorization;
using Core.Interfaces.Users;
using Core.Models;
using Infrastructure.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace BP.Plugin.Monitor.Controllers;

/// <summary>
/// 系统监控
/// </summary>
[Authorize]
[Description("系统监控")]
public class MonitorController : BaseController
{
    private readonly IMonitorDbContext _db;
    private readonly ICurrentUserService _currentUser;
    private static readonly ConcurrentDictionary<Guid, HttpResponse> _sseClients = new();

    public MonitorController(IMonitorDbContext db, ICurrentUserService currentUser)
    {
        _db = db;
        _currentUser = currentUser;
    }

    /// <summary>
    /// 在线用户-分页查询
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [Permission("Online:User:View:Page")]
    [HttpGet("page")]
    [Description("在线用户-分页查询")]
    public async Task<Result<PaginatedData<OnlineUserDto>>> QueryOnlineUsersAsync([FromQuery] OnlineUsersWithPaginationQuery request)
    {
        request.Type = 0;
        return await Result<PaginatedData<OnlineUserDto>>.SucceedAsync(await Mediator.Send(request));
    }

    /// <summary>
    /// 我的登录日志
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    //[Permission("Login:Log:View:Page")]
    [HttpGet("me/login/log/page")]
    [Description("我的登录日志")]
    public async Task<Result<PaginatedData<OnlineUserDto>>> QueryMeLoginLogAsync([FromQuery] OnlineUsersWithPaginationQuery request)
    {
        request.Type = 1;
        return await Result<PaginatedData<OnlineUserDto>>.SucceedAsync(await Mediator.Send(request));
    }

    /// <summary>
    /// 登录日志-分页查询
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [Permission("Login:Log:View:Page")]
    [HttpGet("login/log/page")]
    [Description("登录日志-分页查询")]
    public async Task<Result<PaginatedData<OnlineUserDto>>> QueryLoginLogAsync([FromQuery] OnlineUsersWithPaginationQuery request)
    {
        request.Type = 2;
        return await Result<PaginatedData<OnlineUserDto>>.SucceedAsync(await Mediator.Send(request));
    }

    /// <summary>
    /// 系统日志-分页查询
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [Permission("System:Log:View:Page")]
    [NoLogging]
    [HttpGet("system/log/page")]
    [Description("系统日志-分页查询")]
    public async Task<Result<PaginatedData<SystemLogDto>>> QuerySystemLogsAsync([FromQuery] SystemLogsWithPaginationQuery request)
    {
        return await Result<PaginatedData<SystemLogDto>>.SucceedAsync(await Mediator.Send(request));
    }

    /// <summary>
    /// 操作日志-分页查询
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [Permission("Operation:Log:View:Page")]
    [NoLogging]
    [HttpGet("operation/log/page")]
    [Description("操作日志-分页查询")]
    public async Task<Result<PaginatedData<SystemLogDto>>> QueryOperationLogsAsync([FromQuery] SystemLogsWithPaginationQuery request)
    {
        return await Result<PaginatedData<SystemLogDto>>.SucceedAsync(await Mediator.Send(request));
    }

    /// <summary>
    /// 同步日志
    /// </summary>
    /// <returns></returns>
    [Permission("System:Log:SyncTenant")]
    [HttpPost("tenant/log/sync")]
    [Description("同步日志")]
    public async Task<Result<bool>> TenantLogSyncAsync()
    {       
        return await Mediator.Send(new TenantLogSyncCommand());
    }

    [NoLogging]
    [HttpPost("heartbeat")]
    public async Task<IActionResult> Heartbeat(CancellationToken ct)
    {
        var userId = _currentUser.GetUserId();
        var user = await _db.OnlineUsers.FirstOrDefaultAsync(x => x.UserName == _currentUser.Name && x.IsOnline == true, ct);

        var now = DateTime.UtcNow;
        var ip = HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";
        var userAgent = Request.Headers["User-Agent"].ToString();
        var browser = ParseBrowser(userAgent);
        var os = ParseOS(userAgent);

        if (user != null)
        {
            user.LastActiveTime = now;
            user.IsOnline = true;
            user.IP = ip;
            user.Browser = browser;
            user.System = os;
            user.UserId = userId;
        }
        else
        {
            _db.OnlineUsers.Add(new OnlineUser
            {
                UserId = userId,
                UserName = User.Identity?.Name ?? "Unknown",
                IP = ip,
                Browser = browser,
                System = os,
                LoginTime = now,
                LastActiveTime = now,
                IsOnline = true
            });
        }

        await _db.SaveChangesAsync(ct);
        return Ok();
    }

    /// <summary>
    /// 删除登录日志
    /// </summary>
    /// <returns></returns>
    [Permission("Login:Log:Delete")]
    [HttpDelete("batch/online/log")]
    [Description("删除登录日志")]
    public async Task<Result<bool>> BatchDeleteOnlineLogAsync(BatchDeleteOnlineLogCommand request)
    {
        return await Mediator.Send(request);
    }

    /// <summary>
    /// 删除日志
    /// </summary>
    /// <returns></returns>
    [Permission("Operation:Log:Delete")]
    [Permission("System:Log:Delete")]
    [HttpDelete("batch/log")]
    [Description("删除日志")]
    public async Task<Result<bool>> BatchDeleteLogAsync(BatchDeleteLogCommand request)
    {
        return await Mediator.Send(request);
    }

    /// <summary>
    /// SSE 订阅事件
    /// </summary>
    [NoLogging]
    [HttpGet("subscribe")]
    public async Task Subscribe(CancellationToken ct)
    {
        var userIdStr = User.GetUserId();
        if (!Guid.TryParse(userIdStr, out var userId))
        {
            Response.StatusCode = 401;
            return;
        }

        Response.Headers["Content-Type"] = "text/event-stream";
        Response.Headers["Cache-Control"] = "no-cache";
        Response.Headers["Connection"] = "keep-alive";

        _sseClients[userId] = Response;

        try
        {
            while (!ct.IsCancellationRequested)
            {
                await Task.Delay(5000, ct); // 每5秒检测一次
                var user = await _db.OnlineUsers.FirstOrDefaultAsync(x => x.UserId == userId && x.IsOnline, ct);
                if (user != null && user.IsKicked.HasValue && user.IsKicked.Value == true)
                {
                    await WriteEventAsync(Response, "kick", "您已被管理员踢下线");
                    break; // 发送后断开连接
                }
            }
        }
        catch (TaskCanceledException) { }
        finally
        {
            _sseClients.TryRemove(userId, out _);
        }
    }

    /// <summary>
    /// 管理员踢人接口
    /// </summary>
    [Permission("Kick:OnLine:User")]
    [HttpPost("{id}/kick")]
    [Description("踢人")]
    public async Task<Result<bool>> KickUser(long id)
    {
        var userName = _currentUser.Name;
        var user = await _db.OnlineUsers.FirstOrDefaultAsync(x => x.Id == id && x.IsOnline);
        if (user == null) return Result<bool>.Failure(["用户不存在或已下线"]);

        user.IsOnline = false;
        user.IsKicked = true;
        user.KickedByUserName = userName;
        user.KickedAt = DateTime.UtcNow;

        await _db.SaveChangesAsync();

        var userId = user.UserId.ToString() ?? "";
        // 实时推送
        if (_sseClients.TryGetValue(Guid.Parse(userId), out var resp))
        {
            await WriteEventAsync(resp, "kick", $"您已被管理员:{userName},踢下线");
        }

        return await Result<bool>.SucceedAsync(true);
    }

    // 🧠 简单解析浏览器信息
    private static string ParseBrowser(string userAgent)
    {
        if (userAgent.Contains("Edg")) return "Edge";
        if (userAgent.Contains("Chrome")) return "Chrome";
        if (userAgent.Contains("Firefox")) return "Firefox";
        if (userAgent.Contains("Safari")) return "Safari";
        if (userAgent.Contains("MSIE") || userAgent.Contains("Trident")) return "Internet Explorer";
        return "Unknown";
    }

    // 🧠 简单解析操作系统
    private static string ParseOS(string userAgent)
    {
        if (userAgent.Contains("Windows")) return "Windows";
        if (userAgent.Contains("Mac OS")) return "MacOS";
        if (userAgent.Contains("Linux")) return "Linux";
        if (userAgent.Contains("Android")) return "Android";
        if (userAgent.Contains("iPhone")) return "IOS";
        return "Unknown";
    }

    private static async Task WriteEventAsync(HttpResponse response, string eventName, string data)
    {
        var msg = $"event: {eventName}\ndata: {data}\n\n";
        await response.WriteAsync(msg);
        await response.Body.FlushAsync();
    }
}
